package com.sz.common.core.system.service.impl;

import com.sz.common.base.service.AbstractService;
import com.sz.common.core.system.dto.FileInfoDto;
import com.sz.common.core.system.entity.SysFile;
import com.sz.common.core.system.entity.SysFileGroup;
import com.sz.common.core.system.service.SysFileGroupService;
import com.sz.common.core.system.service.SysFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Function: SysFileServiceImpl <br>
 * Author: Charles <br>
 * Date: 2017-02-17 13:47:00
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class SysFileGroupServiceImpl extends AbstractService implements SysFileGroupService {

    @Autowired
    SysFileService fileService;

    @Override
    protected String getMapperNamespace() {
        return "com.sz.common.core.system.SysFileGroupMapper";
    }

    @Override
    public String generateGroupId() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * @param fileIds
     * @param owners
     * @param description
     * @param domainId
     * @return
     */
    @Override
    public String createFileGroup(List<String> fileIds, String owners, String description, int domainId) {
        if (fileIds == null || fileIds.size() == 0) {
            return null;
        }
        String groupId = generateGroupId();
        this.insertFileToGroup(groupId, fileIds, owners, description, domainId);
        return groupId;
    }

    /**
     * @param groupId
     * @param fileIds
     * @param owners
     * @param description
     * @param domainId
     */
    @Override
    public String saveFileToGroup(String groupId, List<String> fileIds, String owners, String description, int domainId) {
        if (groupId == null || groupId.length() == 0) {
            return createFileGroup(fileIds, owners, description, domainId);
        }
        if (fileIds == null || fileIds.size() == 0) { //Remove all
            this.dao.delete(this.getSqlName("deleteByGroupId"), groupId);
            return "";
        }

        List<String> existFileIds = this.getFileIdsByGroupId(groupId);
        List<String> waitForInsert = new ArrayList<>();
        List<String> waitForDelete = new ArrayList<>();
        fileIds.forEach(fileId -> {
            if (!existFileIds.contains(fileId)) {
                waitForInsert.add(fileId);
            }
        });

        existFileIds.forEach(fileId -> {
            if (!fileIds.contains(fileId)) {
                waitForDelete.add(fileId);
            }
        });

        //delete old fileId
        removeFileFromGroup(groupId, waitForDelete);
        //insert new fileId
        insertFileToGroup(groupId, waitForInsert, owners, description, domainId);
        return groupId;
    }

    /**
     * @param fileIds
     * @param owners
     * @param description
     * @param domainId
     * @return
     */
    @Override
    public void insertFileToGroup(String groupId, List<String> fileIds, String owners, String description, int domainId) {
        if (groupId == null || groupId.length() == 0) {
            throw new IllegalArgumentException("groupId cannot be empty");
        }
        if (fileIds == null || fileIds.size() == 0) {
            return;
        }
        List<SysFileGroup> listGroup = new ArrayList<>();
        List<SysFile> listFile = new ArrayList<>();
        for (String fileId : fileIds) {
            SysFile file = new SysFile();
            file.setFileId(fileId);
            file.setCatalog(owners);
            file.setIsTempFile(false);
            file.setDomainId(domainId);
            listFile.add(file);

            SysFileGroup group = new SysFileGroup();
            group.setGroupId(groupId);
            group.setFileId(fileId);
            group.setOwners(owners);
            group.setDescription(description);
            group.setDomainId(domainId);
            listGroup.add(group);
        }
        fileService.updateFileInfo(listFile);
        this.dao.batchInsert(this.getSqlName("insertSelective"), listGroup);
    }

    @Override
    public void removeFileFromGroup(String groupId, List<String> fileIds) {
        if (groupId == null || groupId.length() == 0) {
            throw new IllegalArgumentException("groupId cannot be empty");
        }
        if (fileIds == null || fileIds.size() == 0) {
            return;
        }
        List<Map<String, String>> list = new ArrayList<>();
        for (String fileId : fileIds) {
            Map<String, String> map = new HashMap<>();
            map.put("groupId", groupId);
            map.put("fileId", fileId);
            list.add(map);
        }
        this.dao.batchDelete(this.getSqlName("deleteByFileId"), list);
    }

    /**
     * @param groupId
     */
    @Override
    public void removeAllFileFromGroup(String groupId) {
        this.dao.delete(this.getSqlName("deleteByGroupId"), groupId);
    }

    /**
     * @param groupId
     * @return
     */
    @Override
    public List<String> getFileIdsByGroupId(String groupId) {
        List<String> fileIds = new ArrayList<>();
        List<SysFileGroup> items = this.dao.findForList(this.getSqlName("selectByGroupId"), groupId, SysFileGroup.class);
        if (items != null && items.size() > 0) {
            items.forEach(item -> fileIds.add(item.getFileId()));
        }
        return fileIds;
    }

    /**
     * @param groupId
     * @return
     */
    @Override
    public List<FileInfoDto> getFileDtosByGroupId(String groupId) {
        List<FileInfoDto> fileDtos = new ArrayList<>();
        List<SysFileGroup> items = this.dao.findForList(this.getSqlName("selectByGroupId"), groupId, SysFileGroup.class);
        if (items != null && items.size() > 0) {
            List<String> fileIds = new ArrayList<>();
            items.forEach(item -> fileIds.add(item.getFileId()));
            List<SysFile> files = this.dao.findForList(
                    ("com.sz.common.core.system.mapper.SysFileMapper.selectByFileIdsNoContent"), fileIds, SysFile.class);
            files.forEach(item -> fileDtos.add(
                    new FileInfoDto(item.getFileId(), item.getFileName(), item.getContentType(), item.getFileLocation())));
        }
        return fileDtos;
    }
}
